this.alphaMap = {
    "Deseret": JSON.parse(readJSON("resource://alphabet/map_deseret.json")),
    "Shavian": JSON.parse(readJSON("resource://alphabet/map_shavian.json")),
};
var cmuDict =  JSON.parse(readJSON("resource://dict/cmudict07a.json"));

self.onmessage = function (e) {
    /*text = e.data[0];*/
    /*udictURI = e.data[1];*/
    /*alphabet = e.data[2];*/
    /*userDict    = JSON.parse( readJSON(udictURI) );*/
    /*self.postMessage(transliterate(text, alphabet));*/
    self.postMessage("nothing");
}


// Check first in any dictionaries provided as an argument, then in the user
// dictionary, then in cmuDict.
function lookup(word) {
    word = word.toUpperCase();
    function tryDict(dict) {
        ph = dict[word];
        if (ph) {
            return ph;
        }
        else {
            return null;
        }
    }
    var result;
    for (var i = 1; i < arguments.length; i++) {   
        if (result = tryDict(arguments[i])) return result;
    }
    if (result = tryDict(userDict)) return result;
    if (result = tryDict(cmuDict))  return result;
    return null;
}


function utfString(codePoints) {
    var str = '';
    for (var i=0; i < codePoints.length; i++) {
        str = str + unicode(codePoints[i]);
    }
    return str;
}


// Plain String.fromCharCode() cannot handle higher codepoints. All characters are stored in
// JSON maps as their numeric codepoints as Firefox's JSON parser cannot handle the characters
// themselves.
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/fromCharCode
function unicode(codePt) {  
    if (codePt > 0xFFFF) {  
        codePt -= 0x10000;  
        return String.fromCharCode(0xD800 + (codePt >> 10), 0xDC00 + (codePt & 0x3FF));  
    }  
    else {  
        return String.fromCharCode(codePt);  
    }  
}


function transliterate(text, alphabet) {
    var splitText = text.split(/(\w+(?:'\w+)|\W+)/g);
    var result = '';
    var map = alphaMap[alphabet];

    for (var i = 0; i < splitText.length; i++) {
        var word = splitText[i];

        if (typeof (abbrev = map.abbreviate[word.toUpperCase()]) != 'undefined') {
            ph = abbrev;
        }
        else {
            ph = latinPhonemes(word, map);
            if (ph.length == 0) {
                result = result + word;
                continue;
            }
        }

        // Check capitalization of the original word and pass it along
        // with the array of phonemes to the actual alphabet-specific
        // function.
        var caps = 0;
        if (word == word.toUpperCase()) {
            caps = 2;
        }
        else if (word.charAt(0) == word.charAt(0).toUpperCase()) {
            caps = 1;
        }
        result = result + transWord(ph, map, caps);
    }
    return result;
}


function transWord(ph, map, caps) {

        // map characters phoneme by phoneme
        var replace, prev = "", result = [];
        for (var i = 0; i < ph.length; i++) {
            var cur = map[ ph[i] ];
            if (typeof cur == 'undefined') return "INVALID";
            if (Array.isArray(cur)) {
                for (var j = 0; j < cur.length; j++) result.push(cur[j]);
                prev = cur[j];
                continue;
            }

            // check for and convert cetain combinations to single characters
            // Only supports two characters at a time for now.
            if (replace = map.compress[ [prev, cur].join('_') ]) {
                result = result.slice(0, result.length-1); // drop last character
                cur = replace;                             // this will replace it
            }
            result.push(cur);
            prev = cur;
        }


        // maintain capitalization in alphabets with capital letters.
        if (map.capsOffset) {
            if (caps == 1) {
                result[0] = result[0] + map.capsOffset;
            }
            else if (caps == 2) {
                result = result.map(function(x) { return x + map.capsOffset });
            }
        }
        return utfString(result);
}


// TODO: Strip accents from loanwords. (Or see if they can be added into the dictionary in 
//       uppercase...)
function latinPhonemes(word, map) {
    var caps = 0, phonemes = [], candidates;
    if (word.match(/'s$/)) {
        // Manually add sound of 's at the end of words. For obvious
        // reasons, CMUdict's list of words ending in 's is not
        // exhaustive. One wonders why they bothered.
        if (candidates = lookup(word.slice(0, word.length-2))) {
            phonemes = candidates[0].slice(0);      // .slice(0) = deep copy.
            var lastPhoneme = phonemes[phonemes.length-1];
            if (["P","T","K","F","TH","HH"].indexOf(lastPhoneme) != -1) {
                phonemes.push("S");
            }
            else if (["CH","JH","S","Z","SH","ZH"].indexOf(lastPhoneme) != -1) {
                phonemes.push("IH0", "Z");
            }
            else {
                phonemes.push("Z");
            }
        }

    }
    else if (candidates = lookup(word)) {
        phonemes = candidates[0];
    }

    return phonemes;
}

function readJSON(uri) {
  /*var req = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]  */
  /*.createInstance(Components.interfaces.nsIXMLHttpRequest);*/
  var req = new XMLHttpRequest();
  req.open('GET', uri, false);
  req.overrideMimeType("application/json");
  req.send(null);
  return req.responseText;
}


